package com.xl.singletonPattern.practice;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
/**
 * 缓存管理器单例 - 使用枚举实现（最佳实践）
 * 枚举方式天然线程安全，且防止反射攻击和序列化问题
 */
public enum CacheManager {
    //单例实例
    INSTANCE;
    //使用线程安全的ConcurrentHashMap作为缓存存储
    private final Map<String,CacheEntry> cache = new ConcurrentHashMap<>();
    //默认过期时间（毫秒）
    private static final long DEFAULT_EXPIRATION_TIME = TimeUnit.MILLISECONDS.toMillis(30);

    /**
     * 存入缓存
     * @param key 键
     * @param value 值
     */
    public void put(String key, Object value) {
        put(key, value, DEFAULT_EXPIRATION_TIME);
    }

    /**
     * 存入缓存（带过期时间）
     * @param key 键
     * @param value 值
     * @param expirationTime 过期时间（毫秒）
     */
    public void put(String key, Object value, long expirationTime) {
        if (key == null || value == null) {
            throw new IllegalArgumentException("Key and value cannot be null.");
        }
        long expirationMillis = System.currentTimeMillis()+expirationTime;
        cache.put(key, new CacheEntry(expirationMillis, value));
        System.out.println("缓存已添加：key="+key+" value="+value+", 过期时间："+expirationTime+"ms");
    }

    /**
     * 获取缓存
     * @param key 键
     * @return 值，如果不存在或已过期则返回null
     */
    public Object get(String key) {
        if (key == null) {
            return null;
        }
        CacheEntry entry = cache.get(key);
        if (entry == null) {
            System.out.println("缓存未找到：key="+key);
            return null;
        }
        if (entry.isExpired()) {
            cache.remove(key);
            System.out.println("缓存已过期：key="+key);
            return null;
        }
        Object value = entry.getValue();
        System.out.println("缓存已找到：key="+key+" value="+value);
        return value;
    }
    /**
     * 获取缓存，带类型转换
     * @param key 键
     * @param clazz 目标类型
     * @return 转换后的值，如果不存在或类型不匹配返回null
     */
    public <T> T get(String key, Class<T> clazz) {
        Object value = get(key);
        if (value == null) {
            return null;
        }
        if (!clazz.isInstance(value)) {
            return null;
        }
        return clazz.cast(value);
    }

    /**
     * 删除指定缓存
     * @param key 键
     * @return 是否删除成功
     */
    public boolean remove(String key) {
        if (key == null) {
            return false;
        }
        Object removedValue = cache.remove(key);
        if (removedValue == null) {
            System.out.println("缓存未找到：key="+key);
            return false;
        }
        System.out.println("缓存已删除：key="+key+" value="+removedValue);
        return true;
    }
    /**
     * 清空缓存
     */
    public void clear() {
        int size = cache.size();
        cache.clear();
        System.out.println("缓存已清空，共清理："+size+"个缓存项");
    }
    /**
     * 获取缓存大小
     * @return 缓存大小
     */
    public int size() {
        return cache.size();
    }
    public int cleanupExpired() {
        int count = 0;
        for (Map.Entry<String, CacheEntry> entry : cache.entrySet()) {
            if (entry.getValue().isExpired()) {
                cache.remove(entry.getKey());
                count++;
            }
        }
        if (count > 0) {
            System.out.println("已清理过期缓存项："+count+"个");
        }
        return count;
    }
    /**
     * 缓存条目内部类
     */
    private static class CacheEntry {
        private final long expirationTime;
        private final Object value;

        public CacheEntry(long expirationTime, Object value) {
            this.expirationTime = expirationTime;
            this.value = value;
        }

        public Object getValue() {
            return value;
        }

        public boolean isExpired() {
            return System.currentTimeMillis() > expirationTime;
        }

        public String toString() {
            return "CacheEntry{expirationTime="+(expirationTime-System.currentTimeMillis())+"ms, value="+value+'}';
        }
    }
}
